package com.tinem.platform.web.auth.page;

import com.alibaba.fastjson.JSON;
import com.tinem.platform.module.starter.jpa.entity.client.ClientChannelDetails;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @author fzh
 * @version v1
 * @program: platform
 * @className PlatformClientDetails
 * @description TODO
 * @site 
 * @company 
 * @create 2020-09-04 09:31
 */
@Data
public class PlatformClientDetails implements ClientDetails {
    private Set<String> scope = Collections.emptySet();
    private Set<String> resourceIds = Collections.emptySet();
    private Set<String> authorizedGrantTypes = Collections.emptySet();
    private Set<String> registeredRedirectUris;
    private Set<String> autoApproveScopes;
    private List<GrantedAuthority> authorities = Collections.emptyList();
    private Integer accessTokenValiditySeconds;
    private Integer refreshTokenValiditySeconds;
    private Map<String, Object> additionalInformation = new LinkedHashMap<String, Object>();

    private ClientChannelDetails clientChannelDetails;

    public PlatformClientDetails(ClientChannelDetails clientChannelDetails){
        this.clientChannelDetails = clientChannelDetails;
        if (StringUtils.hasText(clientChannelDetails.getScope())) {
            Set<String> scopeList = StringUtils.commaDelimitedListToSet(clientChannelDetails.getScope());
            if (!scopeList.isEmpty()) {
                this.scope = scopeList;
            }
        }
        if (StringUtils.hasText(clientChannelDetails.getResourceIds())) {
            Set<String> resources = StringUtils
                    .commaDelimitedListToSet(clientChannelDetails.getResourceIds());
            if (!resources.isEmpty()) {
                this.resourceIds = resources;
            }
        }
        if (StringUtils.hasText(clientChannelDetails.getAuthorizedGrantTypes())) {
            this.authorizedGrantTypes = StringUtils
                    .commaDelimitedListToSet(clientChannelDetails.getAuthorizedGrantTypes());
        } else {
            this.authorizedGrantTypes = new HashSet<>(Arrays.asList(
                    "authorization_code", "refresh_token"));
        }
        if (StringUtils.hasText(clientChannelDetails.getWebServerRedirectUri())) {
            this.registeredRedirectUris = StringUtils
                    .commaDelimitedListToSet(clientChannelDetails.getWebServerRedirectUri());
        }
        if (StringUtils.hasText(clientChannelDetails.getAuthorities())) {
            this.authorities = AuthorityUtils
                    .commaSeparatedStringToAuthorityList(clientChannelDetails.getAuthorities());
        }
        if (StringUtils.hasText(clientChannelDetails.getAdditionalInformation())) {
            this.additionalInformation = JSON.parseObject(clientChannelDetails.getAdditionalInformation());
        }
        if (StringUtils.hasText(clientChannelDetails.getAutoapprove())) {
            this.autoApproveScopes = StringUtils
                    .commaDelimitedListToSet(clientChannelDetails.getAutoapprove());
        }
    }

    @Override
    public String getClientId() {
        return clientChannelDetails.getClietId();
    }

    @Override
    public Set<String> getResourceIds() {
        return this.resourceIds;
    }

    @Override
    public boolean isSecretRequired() {
        return this.clientChannelDetails.getClientSecret() != null;
    }

    @Override
    public String getClientSecret() {
        return this.clientChannelDetails.getClientSecret();
    }

    @Override
    public boolean isScoped() {
        return this.scope != null && !this.scope.isEmpty();
    }

    @Override
    public Set<String> getScope() {
        return this.scope;
    }

    @Override
    public Set<String> getAuthorizedGrantTypes() {
        return this.authorizedGrantTypes;
    }

    @Override
    public Set<String> getRegisteredRedirectUri() {
        return this.registeredRedirectUris;
    }

    @Override
    public Collection<GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    @Override
    public Integer getAccessTokenValiditySeconds() {
        return this.clientChannelDetails.getAccessTokenValidity();
    }

    @Override
    public Integer getRefreshTokenValiditySeconds() {
        return this.clientChannelDetails.getRefreshTokenValidity();
    }

    @Override
    public boolean isAutoApprove(String scope) {
        if (autoApproveScopes == null) {
            return false;
        }
        for (String auto : autoApproveScopes) {
            if ("true".equals(auto) || scope.matches(auto)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Map<String, Object> getAdditionalInformation() {
        return additionalInformation;
    }
}
